<?php
namespace app\common\service;

use support\Log;
use support\Db;
use support\Redis;

/**
 * SDK增强服务
 * 提供错误处理、重试机制、缓存等功能
 */
class SDKService
{
    /**
     * 最大重试次数
     */
    const MAX_RETRY_COUNT = 3;

    /**
     * 重试延迟时间（秒）
     */
    const RETRY_DELAY = 1;

    /**
     * 缓存过期时间（秒）
     */
    const CACHE_TTL = 300; // 5分钟

    /**
     * 请求超时时间（秒）
     */
    const REQUEST_TIMEOUT = 10;

    /**
     * 发送请求并处理错误和重试
     */
    public static function sendRequest($url, $data, $headers = [], $retryCount = 0)
    {
        try {
            // 记录请求日志
            Log::info('SDK Request', [
                'url' => $url,
                'data' => $data,
                'headers' => $headers,
                'retry_count' => $retryCount
            ]);

            // 设置请求选项
            $options = [
                'http' => [
                    'method' => 'POST',
                    'header' => array_merge([
                        'Content-Type: application/json',
                        'User-Agent: XAppTool-SDK/1.0'
                    ], $headers),
                    'content' => json_encode($data),
                    'timeout' => self::REQUEST_TIMEOUT,
                    'ignore_errors' => true
                ]
            ];

            $context = stream_context_create($options);
            $response = @file_get_contents($url, false, $context);

            if ($response === false) {
                throw new \Exception('Failed to connect to server');
            }

            // 解析响应
            $result = json_decode($response, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                throw new \Exception('Invalid JSON response');
            }

            // 记录响应日志
            Log::info('SDK Response', [
                'url' => $url,
                'response' => $result,
                'retry_count' => $retryCount
            ]);

            // 检查响应状态
            if (!isset($result['code']) || $result['code'] !== 200) {
                throw new \Exception($result['msg'] ?? 'Unknown error');
            }

            return [
                'success' => true,
                'data' => $result['data'] ?? [],
                'retry_count' => $retryCount
            ];

        } catch (\Exception $e) {
            Log::error('SDK Request Failed', [
                'url' => $url,
                'error' => $e->getMessage(),
                'retry_count' => $retryCount
            ]);

            // 判断是否重试
            if ($retryCount < self::MAX_RETRY_COUNT) {
                // 指数退避延迟
                $delay = self::RETRY_DELAY * pow(2, $retryCount);
                sleep($delay);
                
                return self::sendRequest($url, $data, $headers, $retryCount + 1);
            }

            return [
                'success' => false,
                'error' => $e->getMessage(),
                'retry_count' => $retryCount
            ];
        }
    }

    /**
     * 获取设备信息并缓存
     */
    public static function getDeviceInfo($fingerprint, $appkey)
    {
        $cacheKey = "device_info:{$appkey}:{$fingerprint}";
        
        // 尝试从缓存获取
        $cached = Redis::get($cacheKey);
        if ($cached) {
            return json_decode($cached, true);
        }

        // 从数据库获取设备信息
        $deviceInfo = Db::name('gf_apps_web')
            ->where('fingerprint', $fingerprint)
            ->where('appkey', $appkey)
            ->order('id', 'desc')
            ->find();

        if ($deviceInfo) {
            // 缓存设备信息
            Redis::setex($cacheKey, self::CACHE_TTL, json_encode($deviceInfo));
            return $deviceInfo;
        }

        return null;
    }

    /**
     * 验证请求参数
     */
    public static function validateRequestParams($params, $requiredFields = [])
    {
        $errors = [];

        foreach ($requiredFields as $field) {
            if (!isset($params[$field]) || empty($params[$field])) {
                $errors[] = "Missing required field: {$field}";
            }
        }

        // 验证appkey格式
        if (isset($params['appkey']) && !preg_match('/^[a-zA-Z0-9]{32}$/', $params['appkey'])) {
            $errors[] = 'Invalid appkey format';
        }

        // 验证版本号格式
        if (isset($params['version']) && !preg_match('/^\d+\.\d+\.\d+$/', $params['version'])) {
            $errors[] = 'Invalid version format';
        }

        // 验证设备指纹格式
        if (isset($params['fingerprint']) && strlen($params['fingerprint']) < 10) {
            $errors[] = 'Invalid fingerprint format';
        }

        return $errors;
    }

    /**
     * 记录SDK使用统计
     */
    public static function logSDKUsage($appkey, $action, $result, $responseTime = null, $platform = null, $sdkVersion = null, $errorMessage = null)
    {
        try {
            // 使用新的SDK统计仓库记录日志
            $statsRepository = Container::make(\app\common\repository\SDKStatsRepository::class);
            $statsRepository->logUsage(
                $appkey, 
                $action, 
                $result ? 'success' : 'error', 
                $responseTime, 
                $errorMessage, 
                $platform, 
                $sdkVersion
            );

            // 更新应用的使用统计（保持向后兼容）
            self::updateAppUsageStats($appkey, $action, $result);

        } catch (\Exception $e) {
            Log::error('Failed to log SDK usage', ['error' => $e->getMessage()]);
        }
    }

    /**
     * 更新应用使用统计
     */
    private static function updateAppUsageStats($appkey, $action, $result)
    {
        $today = date('Y-m-d');
        $statsTable = 'gf_app_usage_stats';

        try {
            // 检查今日统计是否存在
            $exists = Db::name($statsTable)
                ->where('appkey', $appkey)
                ->where('stat_date', $today)
                ->find();

            if ($exists) {
                // 更新现有统计
                $updateData = [];
                if ($result) {
                    $updateData["{$action}_success"] = Db::raw("{$action}_success + 1");
                } else {
                    $updateData["{$action}_failed"] = Db::raw("{$action}_failed + 1");
                }
                $updateData['updated_at'] = date('Y-m-d H:i:s');

                Db::name($statsTable)
                    ->where('appkey', $appkey)
                    ->where('stat_date', $today)
                    ->update($updateData);
            } else {
                // 创建新的统计记录
                $insertData = [
                    'appkey' => $appkey,
                    'stat_date' => $today,
                    'device_info_success' => 0,
                    'device_info_failed' => 0,
                    'install_params_success' => 0,
                    'install_params_failed' => 0,
                    'custom_params_success' => 0,
                    'custom_params_failed' => 0,
                    'event_tracking_success' => 0,
                    'event_tracking_failed' => 0,
                    'created_at' => date('Y-m-d H:i:s'),
                    'updated_at' => date('Y-m-d H:i:s')
                ];

                if ($result) {
                    $insertData["{$action}_success"] = 1;
                } else {
                    $insertData["{$action}_failed"] = 1;
                }

                Db::name($statsTable)->insert($insertData);
            }
        } catch (\Exception $e) {
            Log::error('Failed to update app usage stats', ['error' => $e->getMessage()]);
        }
    }

    /**
     * 获取应用的使用统计
     */
    public static function getAppUsageStats($appkey, $days = 7)
    {
        $startDate = date('Y-m-d', strtotime("-{$days} days"));
        $endDate = date('Y-m-d');

        try {
            $stats = Db::name('gf_app_usage_stats')
                ->where('appkey', $appkey)
                ->whereBetween('stat_date', [$startDate, $endDate])
                ->order('stat_date', 'desc')
                ->select();

            return $stats ?: [];
        } catch (\Exception $e) {
            Log::error('Failed to get app usage stats', ['error' => $e->getMessage()]);
            return [];
        }
    }

    /**
     * 批量处理请求
     */
    public static function batchProcess($requests)
    {
        $results = [];
        $errors = [];

        foreach ($requests as $index => $request) {
            try {
                $result = self::sendRequest(
                    $request['url'],
                    $request['data'],
                    $request['headers'] ?? []
                );
                
                $results[$index] = $result;
            } catch (\Exception $e) {
                $errors[$index] = $e->getMessage();
                $results[$index] = [
                    'success' => false,
                    'error' => $e->getMessage()
                ];
            }
        }

        return [
            'results' => $results,
            'errors' => $errors,
            'total' => count($requests),
            'success_count' => count(array_filter($results, function($r) { return $r['success']; }))
        ];
    }

    /**
     * 获取SDK配置信息
     */
    public static function getSDKConfig($appkey)
    {
        $cacheKey = "sdk_config:{$appkey}";
        
        // 尝试从缓存获取
        $cached = Redis::get($cacheKey);
        if ($cached) {
            return json_decode($cached, true);
        }

        try {
            // 获取应用配置
            $app = Db::name('gf_apps')
                ->where('appkey', $appkey)
                ->where('status', 1)
                ->where('is_del', 0)
                ->find();

            if (!$app) {
                return null;
            }

            $config = [
                'app_name' => $app['name'],
                'appkey' => $app['appkey'],
                'timeout' => self::REQUEST_TIMEOUT,
                'max_retry' => self::MAX_RETRY_COUNT,
                'cache_ttl' => self::CACHE_TTL,
                'features' => [
                    'device_tracking' => true,
                    'install_attribution' => true,
                    'custom_params' => true,
                    'event_tracking' => true
                ],
                'limits' => [
                    'daily_requests' => 10000,
                    'max_devices' => 100000
                ]
            ];

            // 缓存配置
            Redis::setex($cacheKey, self::CACHE_TTL, json_encode($config));

            return $config;

        } catch (\Exception $e) {
            Log::error('Failed to get SDK config', ['error' => $e->getMessage()]);
            return null;
        }
    }
}